package com.then.basic.socket.core;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.SocketTimeoutException;

import org.greenrobot.eventbus.EventBus;


import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import com.then.basic.socket.SocketConfig;
import com.then.basic.socket.core.error.CommonError;

public class TcpRecvThread extends HandlerThread {
	private final static String TAG = "TcpRecvThread";
	final byte PackageFirstHeadTag[] = {SocketConfig.HEADER_INDICATER_0, SocketConfig.HEADER_INDICATER_1, SocketConfig.HEADER_INDICATER_2, SocketConfig.HEADER_INDICATER_3};
	private int sleepTime = 10;
	private DataInputStream dataInput;
	private Registration registration;
	private static final int RecvThreadIsOk = 0;
	private static final int PackageSizeIsNegative = -1;  
	private static final int PackageHeadTagIsError = -2;
	private static final int PackageReadTimeOut = -3;
	private static final int PackageReadError= -4;
	private static final int PackageFirstHeadTagLen = 10;
	private boolean readflag=true;// true 长连接 false 短连接
	private volatile boolean bStoppingThread = false;

	private Handler mPrivateHandler;

	public TcpRecvThread() {
		super("TcpRecvThread");
		start();
		bStoppingThread = false;
	}

	public void SetDataInput(DataInputStream dataInput ,Registration registration) {
		this.dataInput = dataInput;
		this.registration = registration;
	}

//	protected TcpRecvThread(DataInputStream dataInput ,Registration registration) {
//		this.dataInput = dataInput;
//		this.registration = registration;
//	}

	public void stopThread() {
		Log.d(TAG, "Stop!");
		bStoppingThread = true;
		mPrivateHandler.removeCallbacks(runnable);
		quit();
	}

	@Override
	public synchronized void start() {
		super.start();
		Log.d(TAG, "Start!");
		bStoppingThread = false;
	}


	class TcpRecvHandler extends Handler {

		/**
		 * Instantiates a new TcpSendHandler handler.
		 *
		 * @param aLpr the a lpr
		 */
		TcpRecvHandler(Looper aLpr) {
			super(aLpr);
		}

		/*
         * (non-Javadoc)
         *
         * @see android.os.Handler#handleMessage(android.os.Message)
         */
		@Override
		public void handleMessage(Message msg) {
			handleTcpMsg(msg);
		}
	}

	private void handleTcpMsg(Message msg) {
		mPrivateHandler.postDelayed(runnable, 0);
	}

	Runnable runnable = new Runnable() {
		@Override
		public void run() {
			int ret = RecvByteArray();

			// 如果已经在关闭连接了，就不需要再发送接收错误的报告了
			if (bStoppingThread) {
				return;
			}

			closeShortConnect(); // 短连接需要在此时关闭

			if (ret != RecvThreadIsOk) { // 所有的读取错误（包括SOCKET断开、头不对等情况）
				Log.i(TAG, "Send read package fail message. " + registration.getServerType());
				EventBus.getDefault().post(new CommonError.NetworkErrorInfo(
						CommonError.NetworkErrorInfo.ErrorType.ReadPackageFail, 0, 0));
			}

			if (ret == PackageReadError) { // SOCKET断开
				Log.i(TAG, "Send socket disconnected message. "  + registration.getServerType());
				EventBus.getDefault().post(new CommonError.NetworkErrorInfo(
						CommonError.NetworkErrorInfo.ErrorType.ReadSocketDisconnected, 0, 0));
				stopThread(); // 断开之后不再继续读取，防止死循环
				return;
			}
			if (!readflag) {
				return;
			}

			//用延迟任务来替代while sleep 方式
			mPrivateHandler.postDelayed(this, sleepTime);
		}
	};


	public void startTask() {
		if (!isAlive()) {
			try {
				start();
			} catch (IllegalThreadStateException e) {
				throw e;
			}
		}

		if (mPrivateHandler == null) {
			mPrivateHandler = new TcpRecvHandler(getLooper());
		}

		mPrivateHandler.obtainMessage(0).sendToTarget();
	}

//	public void run() {
//		int ret = RecvThreadIsOk;
//		while (ret == RecvThreadIsOk && readflag) {
//			ret = RecvByteArray();
//			// 如果已经在关闭连接了，就不需要再发送接收错误的报告了
//			if (bStoppingThread) {
//				break;
//			}
//			if (ret != RecvThreadIsOk) { // 所有的读取错误（包括SOCKET断开、头不对等情况）
//				MainActivity.handler.sendEmptyMessage(Data.ReadPackageFail);
//			}
//			if (ret == PackageReadError) { // SOCKET断开
//				MainActivity.handler.sendEmptyMessage(Data.ReadSocketDisconnected);
//			}
//			try {
//				sleep(sleepTime);
//			} catch (InterruptedException e) {
//				e.printStackTrace();
//				break;
//			}
//		}
//	}
	private boolean checkFirstPackageHeadTag(byte []temp){
		if(temp[0] != PackageFirstHeadTag[0])return false;
		if(temp[1] != PackageFirstHeadTag[1])return false;
		if(temp[2] != PackageFirstHeadTag[2])return false;
		if(temp[3] != PackageFirstHeadTag[3])return false;
		return true;
	}
	private int getPackageSize(byte []temp){
		int size = ((int)(temp[SocketConfig.SRP_SIZE_HIGH]&0xff) <<8) | (int)(temp[SocketConfig.SRP_SIZE_LOW]&0xff);
		return size;
	}
	private int RecvByteArray(){
		byte[] smallBuffer = new byte[PackageFirstHeadTagLen];
		int offset = 0, i = 0;
		int len = PackageFirstHeadTagLen;
		int packageSize = 0;
		while (offset < len) {
			int length = 0;
			try {
				if (dataInput != null && registration.socketIsConnect()) {
					length = dataInput.read(smallBuffer, offset, (len - offset));
				} else {
					length = -1;
				}
				if (length <= 0) {
					Log.e(TAG, "Read socket returns " + length);
					return PackageReadError;
				}
			} catch (IOException e) {
				if (e instanceof SocketTimeoutException) {
					Log.e(TAG, "Read socket timed out!");
				} else {
					Log.e(TAG, "Read socket IOException!");
				}
				return PackageReadError;
			}
			offset += length;
		}
		if (!checkFirstPackageHeadTag(smallBuffer)) {
			Log.e(TAG, "Head check failed!");
			return PackageHeadTagIsError;
		}
		packageSize = getPackageSize(smallBuffer);
		if (packageSize <= 0) {
			Log.e(TAG, "Package size is negative!");
			return PackageSizeIsNegative;
		}
		byte[] temp = new byte[packageSize];
		for (; i < PackageFirstHeadTagLen; i++) {
			temp[i] = smallBuffer[i];
		}
		len = packageSize;
		offset = PackageFirstHeadTagLen;
		long currenttime = System.currentTimeMillis();
		while (offset < len) {
			int length = 0;
			if (System.currentTimeMillis() - currenttime >= 8000) {
				Log.e(TAG, "Read Package Time Out!");
				return PackageReadTimeOut;
			}
			try {
				if (dataInput != null) {
					length = dataInput.read(temp, offset, (len - offset));
				} else {
					length = -1;
				}
				if (length == -1) {
					break;
				}

			} catch (IOException e) {
				e.printStackTrace();
				Log.e(TAG, "Read Package IOException!");
				return PackageReadError;
			}
			offset += length;
		}
		action(temp);
		return RecvThreadIsOk;	
	}	
	private void action(byte[] data) {
		ClientRequest request = new ClientRequest(data);
		if (registration.getSocketType() != 0){ // 如果是长连接，收到数据包后更新时间
			registration.setUpdatetime();
		}
		if (request.getBody() != null) {
			EventBus.getDefault().post(request.getBody());
		}
	}

	private void closeShortConnect() {
		if (registration.getSocketType() == 0) { // 如果是短连接，收到数据包后关闭socket
			registration.close();
			readflag = false;
		}
	}
}